package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.ruoyi.common.constant.ConfigConstant;
import com.ruoyi.common.constant.StatusConstant;
import com.ruoyi.common.constant.TextConstant;
import com.ruoyi.common.constant.TypeConstant;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.JsonUtil;
import com.ruoyi.common.utils.SmsbaoUtil;
import com.ruoyi.common.utils.YunJiSmsUtil;
import com.ruoyi.system.domain.SmsSendRecord;
import com.ruoyi.system.domain.SmsValidateCode;
import com.ruoyi.system.mapper.SmsSendRecordMapper;
import com.ruoyi.system.service.ISmsSendRecordService;
import com.ruoyi.system.service.ISysConfigService;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.tree.DefaultText;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 短信发送记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-12-28
 */
@Service
public class SmsSendRecordServiceImpl implements ISmsSendRecordService 
{
    @Autowired
    private SmsSendRecordMapper smsSendRecordMapper;

    private Logger logger = LogManager.getLogger(this.getClass());
    @Value("${sms.aliyun.regionid}")
    private String aliyunregionId;
    @Value("${sms.aliyun.accesskeyid}")
    private String aliyunAccesskeyId;
    @Value("${sms.aliyun.secret}")
    private String aliyunSecret;

    @Value("${sms.aliyun.templateid}")
    private String templateid;
    @Value("${sms.aliyun.signname}")
    private String signName;

    @Autowired
    private ISysConfigService baseSysConfigService;


    @Autowired
    private SmsValidateCodeServiceImpl smsValidateCodeService;

    /**
     * 解析回执ID
     *
     * @param xml
     * @return
     */
    public static String getYunJiSmsResultId(String xml) {
        if (StringUtils.isBlank(xml)) {
            return null;
        }
        String resultId = "";
        try {
            Document document = null;
            document = DocumentHelper.parseText(xml);
            Element response = document.getRootElement();
            if (null != response) {
                List elements = response.content();
                for (Object e : elements) {
                    if (e instanceof DefaultText) {
                        resultId = ((DefaultText) e).getText();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultId;
    }

    /**
     * 获取短信验证码-登录
     *
     * @param mobile
     * @return
     */
    public Map<String, Object> sendValidateCodeSms(String mobile) {
        return sendValidateCodeSms(mobile, TypeConstant.BUSINESS_TYPE_LOGIN);
    }
    /**
     * 获取短信验证码
     *
     * @param mobile
     * @return
     */
    public Map<String, Object> sendValidateCodeSms(String mobile, String businessType) {
        Map<String, Object> resMap = new HashMap<String, Object>();
        try {
            // 判断是否为允许密码登录的用户
            String EMPS_LOGIN_WITHPWD = baseSysConfigService.getItemValueByItemKey(ConfigConstant.EMPS_LOGIN_WITHPWD, "");
            if (StringUtils.isNotBlank(EMPS_LOGIN_WITHPWD)) {
                String[] emps = EMPS_LOGIN_WITHPWD.split(",");
                if (ArrayUtils.isNotEmpty(emps)) {
                    for (String emp : emps) {
                        String[] pwdInfo = emp.split(":");
                        String m = pwdInfo[0];
                        if (m.equals(mobile)) {
                            resMap.put("errorNo", StatusConstant.VALIDATECODE_NO);
                            resMap.put("errorInfo", "该手机号无需获取验证码，请直接用分配的验证码进行登录");
                            return resMap;
                        }
                    }
                }
            }
            // 生成验证码
            String validateCode = smsValidateCodeService.generateValidateCode(mobile);
            // 如果不需要发送短信， 直接返回
            String needSendSms = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_SEND_CONTROL_LOGIN, "false");
            if ("false".equals(needSendSms)) {
                resMap.put("errorNo", 0);
                resMap.put("errorInfo", "");
                return resMap;
            }
            // 生成短信内容
			/*String smsContent = generateSmsContent(validateCode, businessType);
			if(StringUtils.isBlank(smsContent)){
				resMap.put("errorNo", -1);
				resMap.put("errorInfo", TextConstant.SMS_CONTENT_EMPTY);
				return resMap;
			}*/
            // 发送短信
            Map<String, String> param = new HashMap<>();
            param.put("code", validateCode);
            // 登录短信根据配置控制是走短信宝还是阿里云
            int smsPlatform = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_SEND_PLATFORM, 1);
            if (smsPlatform == 1) {
                // 阿里云-美港
                resMap = sendSms(mobile, param, businessType);
            } else if (smsPlatform == 2) {
                // 短信宝
                String content = generateSmsContent(validateCode, businessType);
                resMap = sendSms(mobile, content, businessType);
            } else if (smsPlatform == 3) {
                // 阿里云-本账号
                resMap = sendSmsSelfAliyun(mobile, param, businessType);
            } else if (smsPlatform == 4) {
                // 云集短信
                String content = generateSmsContent(validateCode, businessType);
                resMap = sendYunJiSms(mobile, content, businessType);
            }
        } catch (Exception e) {
            logger.error(e);
            resMap.put("errorNo", -1);
            resMap.put("errorInfo", TextConstant.SMS_SEND_FAIL);
        }
        return resMap;
    }
    /**
     * 发送短信-阿里云美港
     *
     * @param mobile       手机号
     * @param businessType 短信类别
     * @return
     */
    public Map<String, Object> sendSms(String mobile, Map<String, String> params, String businessType) {
        Map<String, Object> resMap = new HashMap<String, Object>();
        try {
            String templateCode = "";
            if (TypeConstant.BUSINESS_TYPE_LOGIN.equals(businessType)) {
                templateCode = "SMS_274625246";// 登录验证码短信  "{\"code\":\"540302\"}"
            } else if (TypeConstant.BUSINESS_TYPE_VALICODE.equals(businessType)) {
                templateCode = "SMS_206650616";// 身份验证短信 "{\"code\":\"540302\"}"
            } else if (TypeConstant.BUSINESS_TYPE_NEWDATA.equals(businessType)) {
                templateCode = "SMS_206860062";// 客户通知短信 "{\"NAME\":\"测试\",\"MOBILE\":\"18211112333\"}"
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", TextConstant.SMS_TEMPLATE_NOTEXISTS);
                return resMap;
            }
            String paramStr = JsonUtil.map2json(params);
            DefaultProfile profile = DefaultProfile.getProfile(aliyunregionId, aliyunAccesskeyId, aliyunSecret);
            IAcsClient client = new DefaultAcsClient(profile);
            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain("dysmsapi.aliyuncs.com");
            request.setSysVersion("2017-05-25");
            request.setSysAction("SendSms");
            request.putQueryParameter("SignName", "美港服务");
            request.putQueryParameter("RegionId", aliyunregionId);
            request.putQueryParameter("PhoneNumbers", mobile);
            request.putQueryParameter("TemplateCode", templateCode);
            request.putQueryParameter("TemplateParam", paramStr);
            logger.info(String.format("短信请求：向用户[%s]发送短信类别[%s]参数[%s]", mobile, businessType, paramStr));
            CommonResponse response = client.getCommonResponse(request);
            Map<String, Object> result = (Map) JSONObject.parse(response.getData());
            logger.info(String.format("短信响应：向用户[%s]发送短信类别[%s]响应[%s]", mobile, businessType, result.toString()));
            if ("OK".equals(MapUtils.getString(result, "Code", "ERROR"))) {
                SmsSendRecord smsSendRecord = new SmsSendRecord();
                smsSendRecord.setBusinessType(businessType);
                smsSendRecord.setMobile(mobile);
                smsSendRecord.setContent(paramStr);
                smsSendRecord.setStatus(0L);
                smsSendRecord.setCreateTime(new Date());
                smsSendRecord.setSendId(MapUtils.getString(result, "RequestId", ""));
                smsSendRecord.setSendResult(MapUtils.getString(result, "Message", TextConstant.SMS_SEND_SUCESS));
                this.insertSmsSendRecord(smsSendRecord);
                resMap.put("errorNo", 0);
                resMap.put("errorInfo", TextConstant.SMS_SEND_SUCESS);
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", MapUtils.getString(result, "Message", TextConstant.SMS_SEND_FAIL));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e);
            resMap.put("errorNo", -1);
            resMap.put("errorInfo", TextConstant.SMS_SEND_FAIL);
        }
        return resMap;
    }
    /**
     * 发送短信-短信宝
     *
     * @param mobile       手机号
     * @param businessType 短信类别
     * @return
     */
    public Map<String, Object> sendSms(String mobile, String content, String businessType) {
        Map<String, Object> resMap = new HashMap<>();
        try {
            if (StringUtils.isBlank(content)) {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", "未配置短信模板");
                return resMap;
            }
            logger.info(String.format("短信宝请求：向用户[%s]发送短信类别[%s]内容[%s]", mobile, businessType, content));
            String result = SmsbaoUtil.sendSms(content, mobile);
            logger.info(String.format("短信宝响应：向用户[%s]发送短信类别[%s]响应[%s]", mobile, businessType, result));
            if ("0".equals(result)) {
                SmsSendRecord smsSendRecord = new SmsSendRecord();
                smsSendRecord.setBusinessType(businessType);
                smsSendRecord.setMobile(mobile);
                smsSendRecord.setContent(content);
                smsSendRecord.setStatus(0L);
                smsSendRecord.setCreateTime(new Date());
                smsSendRecord.setSendId("");
                smsSendRecord.setSendResult(result);
                this.insertSmsSendRecord(smsSendRecord);
                resMap.put("errorNo", 0);
                resMap.put("errorInfo", TextConstant.SMS_SEND_SUCESS);
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", "短信发送失败，错误码：" + result);
            }
        } catch (Exception e) {
            logger.error("短信宝发送异常：", e.getMessage());
            resMap.put("errorNo", -1);
            resMap.put("errorInfo", TextConstant.SMS_SEND_FAIL);
        }
        return resMap;
    }
    public String generateSmsContent(String validateCode, String businessType) {
        String template = "";
        if (businessType.equals(TypeConstant.BUSINESS_TYPE_LOGIN)) {
            template = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_TEMPLATE_LOGIN, "您本次登录的验证码为${VALIDATE_CODE}。");
        } else if (businessType.equals(TypeConstant.BUSINESS_TYPE_VALICODE)) {
            template = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_TEMPLATE_VERIFY, "您本次操作的验证码为${VALIDATE_CODE}。");
        }
        return template.replace("{code}", validateCode);
    }

    /**
     * 发送短信-当前主体阿里云账号
     *
     * @param mobile       手机号
     * @param businessType 短信类别
     * @return
     */
    public Map<String, Object> sendSmsSelfAliyun(String mobile, Map<String, String> params, String businessType) {
        Map<String, Object> resMap = new HashMap<String, Object>();
        try {
            String templateCode = "";
            if (TypeConstant.BUSINESS_TYPE_LOGIN.equals(businessType)) {
                templateCode =templateid;// 登录验证码短信  "{\"code\":\"540302\"}"
            } else if (TypeConstant.BUSINESS_TYPE_VALICODE.equals(businessType)) {
                templateCode = templateid;// 身份验证短信 "{\"code\":\"540302\"}"
            } else if (TypeConstant.BUSINESS_TYPE_NEWDATA.equals(businessType)) {
                templateCode = "SMS_206860062";// 客户通知短信 "{\"NAME\":\"测试\",\"MOBILE\":\"18211112333\"}"
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", TextConstant.SMS_TEMPLATE_NOTEXISTS);
                return resMap;
            }
            String paramStr = JsonUtil.map2json(params);
            DefaultProfile profile = DefaultProfile.getProfile(aliyunregionId,
                    aliyunAccesskeyId,
                    aliyunSecret);
            IAcsClient client = new DefaultAcsClient(profile);
            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain("dysmsapi.aliyuncs.com");
            request.setSysVersion("2017-05-25");
            request.setSysAction("SendSms");
            request.putQueryParameter("SignName", signName);
            request.putQueryParameter("PhoneNumbers", mobile);
            request.putQueryParameter("TemplateCode", templateCode);
            request.putQueryParameter("TemplateParam", paramStr);
            logger.info(String.format("短信请求：向用户[%s]发送短信类别[%s]参数[%s]", mobile, businessType, paramStr));
            CommonResponse response = client.getCommonResponse(request);
            Map<String, Object> result = (Map) JSONObject.parse(response.getData());
            logger.info(String.format("短信响应：向用户[%s]发送短信类别[%s]响应[%s]", mobile, businessType, result.toString()));
            if ("OK".equals(MapUtils.getString(result, "Code", "ERROR"))) {
                SmsSendRecord smsSendRecord = new SmsSendRecord();
                smsSendRecord.setBusinessType(businessType);
                smsSendRecord.setMobile(mobile);
                smsSendRecord.setContent(paramStr);
                smsSendRecord.setStatus(0L);
                smsSendRecord.setCreateTime(new Date());
                smsSendRecord.setSendId(MapUtils.getString(result, "RequestId", ""));
                smsSendRecord.setSendResult(MapUtils.getString(result, "Message", TextConstant.SMS_SEND_SUCESS));
                this.insertSmsSendRecord(smsSendRecord);
                resMap.put("errorNo", 0);
                resMap.put("errorInfo", TextConstant.SMS_SEND_SUCESS);
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", MapUtils.getString(result, "Message", TextConstant.SMS_SEND_FAIL));
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e);
            resMap.put("errorNo", -1);
            resMap.put("errorInfo", TextConstant.SMS_SEND_FAIL);
        }
        return resMap;
    }

    /**
     * 发送短信-云集
     *
     * @param mobile       手机号
     * @param businessType 短信类别
     * @return
     */
    public Map<String, Object> sendYunJiSms(String mobile, String content, String businessType) {
        Map<String, Object> resMap = new HashMap<>();
        try {
            if (StringUtils.isBlank(content)) {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", "未配置短信模板");
                return resMap;
            }
            String url = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_YUNJI_URL, "");
            String userCode = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_YUNJI_USERCODE, "");
            String userPass = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_YUNJI_USERPASS, "");

            logger.info(String.format("云集短信请求：向用户[%s]发送短信内容[%s]", mobile, content));
            String result = YunJiSmsUtil.sendSms(url, userCode, userPass, mobile, content);
            logger.info(String.format("云集短信响应：向用户[%s]发送短信响应[%s]", mobile, result));
            if (StringUtils.isNotBlank(result)) {
                String resultId = getYunJiSmsResultId(result);
                SmsSendRecord smsSendRecord = new SmsSendRecord();
                smsSendRecord.setBusinessType(businessType);
                smsSendRecord.setMobile(mobile);
                smsSendRecord.setContent(content);
                smsSendRecord.setStatus(0L);
                smsSendRecord.setCreateTime(new Date());
                smsSendRecord.setSendId(resultId);
                smsSendRecord.setSendResult(result.length() >= 200 ? result.substring(0, 200) : result);
                this.insertSmsSendRecord(smsSendRecord);
                if (StringUtils.isNotBlank(resultId)) {
                    resMap.put("errorNo", 0);
                    resMap.put("errorInfo", TextConstant.SMS_SEND_SUCESS);
                } else {
                    resMap.put("errorNo", -1);
                    resMap.put("errorInfo", "短信发送失败, 请联系管理员。");
                }
            } else {
                resMap.put("errorNo", -1);
                resMap.put("errorInfo", "短信发送失败，错误码：" + result);
            }
        } catch (Exception e) {
            logger.error("云集短信发送异常：", e.getMessage());
            resMap.put("errorNo", -1);
            resMap.put("errorInfo", TextConstant.SMS_SEND_FAIL);
        }
        return resMap;
    }

    /**
     * 校验短信验证码
     *
     * @param mobile
     * @param validateCode
     * @return
     */
    public Map<String, Object> verifyValidateCode(String mobile, String validateCode) {
        Map<String, Object> resMap = new HashMap<String, Object>();
        try {
            int errorNo = StatusConstant.VALIDATECODE_NORMAL;
            // 判断是否为允许密码登录的用户
            String EMPS_LOGIN_WITHPWD = baseSysConfigService.getItemValueByItemKey(ConfigConstant.EMPS_LOGIN_WITHPWD, "");
            if (StringUtils.isNotBlank(EMPS_LOGIN_WITHPWD)) {
                String[] emps = EMPS_LOGIN_WITHPWD.split(",");
                if (ArrayUtils.isNotEmpty(emps)) {
                    for (String emp : emps) {
                        String[] pwdInfo = emp.split(":");
                        String m = pwdInfo[0];
                        String p = pwdInfo[1];
                        if (m.equals(mobile)) {
                            if (p.equals(validateCode)) {
                                resMap.put("errorNo", StatusConstant.VALIDATECODE_NORMAL);
                                logger.info(String.format("手机号%s被允许密码登录", mobile));
                                return resMap;
                            } else {
                                logger.error(String.format("手机号%s登录密码错误", mobile));
                                // 验证码错误
                                resMap.put("errorNo", StatusConstant.VALIDATECODE_ERROR);
                                resMap.put("errorInfo", TextConstant.VALIDATECODE_ERROR);
                                return resMap;
                            }
                        }
                    }
                }
            }
            SmsValidateCode smsValidateCode = smsValidateCodeService.getByMobile(mobile);
            if (smsValidateCode == null) {
                // 验证码未生成
                resMap.put("errorNo", StatusConstant.VALIDATECODE_NOT_CREATE);
                resMap.put("errorInfo", TextConstant.VALIDATECODE_NOT_CREATE);
                return resMap;
            }
            if (!validateCode.equals(smsValidateCode.getContent())) {
                // 验证码错误
                resMap.put("errorNo", StatusConstant.VALIDATECODE_ERROR);
                resMap.put("errorInfo", TextConstant.VALIDATECODE_ERROR);
                return resMap;
            }
            if (validateCode.equals(smsValidateCode.getContent())) {
                int expiredTime = baseSysConfigService.getItemValueByItemKey(ConfigConstant.SMS_VALIDATECODE_TIMEOUT, 300);
                if (System.currentTimeMillis() > smsValidateCode.getCreateTime().getTime() + expiredTime * 1000) {
                    //如果验证时间大于创建时间超过指定时间
                    resMap.put("errorNo", StatusConstant.VALIDATECODE_EXPIRED);
                    resMap.put("errorInfo", TextConstant.VALIDATECODE_EXPIRED);
                    return resMap;
                }
                if (StatusConstant.VALIDATECODE_STATUS_VERIFY == smsValidateCode.getStatus()) {
                    //如果验证码已经被使用
                    resMap.put("errorNo", StatusConstant.VALIDATECODE_EXPIRED);
                    resMap.put("errorInfo", TextConstant.VALIDATECODE_EXPIRED);
                    return resMap;
                }
                //更新验证码表
                smsValidateCode.setStatus(StatusConstant.VALIDATECODE_STATUS_VERIFY);
                smsValidateCode.setVerifyTime(new Date());
                smsValidateCodeService.updateSmsValidateCode(smsValidateCode);
            }
            resMap.put("errorNo", StatusConstant.VALIDATECODE_NORMAL);
            return resMap;
        } catch (Exception e) {
            logger.error(e);
            resMap.put("errorNo", StatusConstant.VALIDATECODE_FAIL);
            resMap.put("errorInfo", TextConstant.VALIDATECODE_FAIL);
        }
        return resMap;
    }
    /**
     * 查询短信发送记录
     * 
     * @param id 短信发送记录主键
     * @return 短信发送记录
     */
    @Override
    public SmsSendRecord selectSmsSendRecordById(Long id)
    {
        return smsSendRecordMapper.selectSmsSendRecordById(id);
    }

    /**
     * 查询短信发送记录列表
     * 
     * @param smsSendRecord 短信发送记录
     * @return 短信发送记录
     */
    @Override
    public List<SmsSendRecord> selectSmsSendRecordList(SmsSendRecord smsSendRecord)
    {
        return smsSendRecordMapper.selectSmsSendRecordList(smsSendRecord);
    }

    /**
     * 新增短信发送记录
     * 
     * @param smsSendRecord 短信发送记录
     * @return 结果
     */
    @Override
    public int insertSmsSendRecord(SmsSendRecord smsSendRecord)
    {
        smsSendRecord.setCreateTime(DateUtils.getNowDate());
        return smsSendRecordMapper.insertSmsSendRecord(smsSendRecord);
    }

    /**
     * 修改短信发送记录
     * 
     * @param smsSendRecord 短信发送记录
     * @return 结果
     */
    @Override
    public int updateSmsSendRecord(SmsSendRecord smsSendRecord)
    {
        return smsSendRecordMapper.updateSmsSendRecord(smsSendRecord);
    }

    /**
     * 批量删除短信发送记录
     * 
     * @param ids 需要删除的短信发送记录主键
     * @return 结果
     */
    @Override
    public int deleteSmsSendRecordByIds(Long[] ids)
    {
        return smsSendRecordMapper.deleteSmsSendRecordByIds(ids);
    }

    /**
     * 删除短信发送记录信息
     * 
     * @param id 短信发送记录主键
     * @return 结果
     */
    @Override
    public int deleteSmsSendRecordById(Long id)
    {
        return smsSendRecordMapper.deleteSmsSendRecordById(id);
    }



}
